#pragma once
#include "requestor.hpp"

namespace yjz_rpc
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallBack = std::function<void(const Json::Value&)>;

            RpcCaller(const Requestor::ptr& req)
                : _requestor(req)
            {}

            // requestor中的处理是针对BaseMessage进行处理的
            // 在RpcCaller中针对结果的处理是针对RpcResponse里边的result进行的
            bool call(const BaseConnection::ptr& conn, const std::string& method, 
                const Json::Value& params, Json::Value& result)
            {
                // 1.组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                BaseMessage::ptr rsp_msg;
                // 2.发送请求
                bool res = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), rsp_msg);
                if (res == false)
                {
                    LOG(LogLevel::ERROR) << "同步Rpc请求失败！";
                    return false;
                }
                // 3.等待响应
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);
                if (rpc_rsp_msg == nullptr)
                {
                    LOG(LogLevel::ERROR) << "Rpc响应类型转换失败！";
                    return false;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR) << "Rpc请求出错: " << errReason(rpc_rsp_msg->rcode());
                    return false;
                }
                result = rpc_rsp_msg->result();
                return true;
            }

            bool call(const BaseConnection::ptr& conn, const std::string& method, 
                const Json::Value& params, JsonAsyncResponse& result)
            {
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                
                // 这里使用智能指针管理，否则出作用域被释放
                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallBack cb = std::bind(&RpcCaller::Callback_1, this, json_promise, std::placeholders::_1);
                bool res = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), cb);
                if (res == false)
                {
                    LOG(LogLevel::ERROR) << "异步Rpc请求失败！";
                    return false;
                }
                return true;
            }

            bool call(const BaseConnection::ptr& conn, const std::string& method, 
                const Json::Value& params, const JsonResponseCallBack& cb)
            {
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);

                Requestor::RequestCallBack req_cb = std::bind(&RpcCaller::Callback_2, this, cb, std::placeholders::_1);
                bool res = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), req_cb);
                if (res == false)
                {
                    LOG(LogLevel::ERROR) << "回调Rpc请求失败！";
                    return false;
                }
                return true;
            }
        private:
            void Callback_1(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr& msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (rpc_rsp_msg == nullptr)
                {
                    LOG(LogLevel::ERROR) << "Rpc响应类型转换失败！";
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR) << "Rpc异步请求出错: " << errReason(rpc_rsp_msg->rcode());
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }

            void Callback_2(const JsonResponseCallBack& cb, const BaseMessage::ptr& msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (rpc_rsp_msg == nullptr)
                {
                    LOG(LogLevel::ERROR) << "Rpc响应类型转换失败！";
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR) << "Rpc回调请求出错: " << errReason(rpc_rsp_msg->rcode());
                    return;
                }
                cb(rpc_rsp_msg->result());
            }
        private:
            Requestor::ptr _requestor;
        };
    }
}